package com.bbs.aop;

import com.bbs.utils.MyUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;

import java.io.Serializable;
import java.util.Date;
import java.util.Objects;
import java.util.stream.Stream;

/**
 * 拦截控制器切面类
 */
@Aspect
@Component("controllerInterceptor")
public class ControllerInterceptor {
    private static final Logger log = LoggerFactory.getLogger(ControllerInterceptor.class);

//    @Pointcut("@annotation(org.springframework.web.bind.annotation.RequestMapping)")
    @Pointcut("execution(* com.bbs.controller..*(..))")
    public void controllerMethodPointcut() {
    }
    /**
     * 请求方法前打印内容
     *
     * @param point
     */
    @Before("controllerMethodPointcut()")
    public void doBefore(JoinPoint point) throws Exception {
        System.out.println("请求开始时间==>"+MyUtil.formatDate(new Date()));
        MethodSignature signature = (MethodSignature) point.getSignature();
        Long count = Stream.of(signature.getMethod().getDeclaredAnnotations())
                .filter(annotation -> annotation.annotationType() == RequestMapping.class)
                .count();
        String requestPath = count >= 1 ? signature.getMethod().getAnnotation(RequestMapping.class).value()[0] : "";

        String info = String.format("URL:%s | %s", requestPath, getMethodInfo(point));
        System.out.println(info);
        System.out.println("请求结束时间==>"+MyUtil.formatDate(new Date()));
    }

    /**
     * 请求完毕后执行
     * @param
     */
    @AfterReturning(returning = "obj",pointcut ="controllerMethodPointcut()")
    public void doAfter(Object obj) throws Throwable {
        String result = null;
        if(obj instanceof Serializable){
            result =  obj.toString();
        }else {
            if(obj != null) {
                try {
                    ObjectMapper objectMapper = new ObjectMapper();
                    result = objectMapper.writeValueAsString(obj);
                } catch (JsonProcessingException e) {
                    log.error("doAfterReturing obj to json exception obj={},msg={}",obj,e);
                }
            }
        }
        System.out.println("响应数据==>"+result);
    }


    private String getMethodInfo(JoinPoint point) {
        String className = point.getSignature().getDeclaringType().getSimpleName();
        String methodName = point.getSignature().getName();
        String[] parameterNames = ((MethodSignature) point.getSignature()).getParameterNames();
        StringBuilder sb = null;
        if (Objects.nonNull(parameterNames)) {
            sb = new StringBuilder();
            for (int i = 0; i < parameterNames.length; i++) {
                String value = point.getArgs()[i] != null ? point.getArgs()[i].toString() : "null";
                sb.append(parameterNames[i] + ":" + value + "; ");
            }
        }
        sb = sb == null ? new StringBuilder() : sb;
        String info = String.format("控制器:%s | 请求方法名:%s | 参数:%s", className, methodName, sb.toString());
        return info;
    }
}
